package com.credithc.signature.common.utils;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.*;
import java.net.URL;
import java.util.Date;
import java.util.List;

/**
 * 描 述:上传文件到S3<br/>
 * 作 者: hujingbo<br/>
 * 创 建：2019/1/21 10:26<br/>
 * 版 本：v1.0.0<br>
 * <p>
 * 历 史: (版本) 作者 时间 注释 <br/>
 */
@Slf4j
@Component
public class AmazonUtil {

    //---------------------------jflow----------------------------

    private static String JFLOW_AMAZON_AWS_ACCESS_KEY="DLXD8FN9SSDORZNH1U5W";
    private static String JFLOW_AMAZON_AWS_SECRET_KEY="THCeGEYiDL1cloU9U1amWeLV0qDOts0Nuem64o8n";
    private static String JFLOW_AMAZON_AWS_BUCKET="eisjflow";
    private static String JFLOW_AMAZON_ENDPOINT_URL="10.100.13.77";

    @Value("${aws.jflow.access.key:DLXD8FN9SSDORZNH1U5W}")
    public void setJflowAmazonAwsAccessKey(String jflowAmazonAwsAccessKey) {
        JFLOW_AMAZON_AWS_ACCESS_KEY = jflowAmazonAwsAccessKey;
    }

    @Value("${aws.jflow.secret.key:THCeGEYiDL1cloU9U1amWeLV0qDOts0Nuem64o8n}")
    public void setJflowAmazonAwsSecretKey(String jflowAmazonAwsSecretKey) {
        JFLOW_AMAZON_AWS_SECRET_KEY = jflowAmazonAwsSecretKey;
    }

    @Value("${aws.jflow.s3.bucket:eisjflow}")
    public void setJflowAmazonAwsBucket(String jflowAmazonAwsBucket) {
        JFLOW_AMAZON_AWS_BUCKET = jflowAmazonAwsBucket;
    }

    @Value("${aws.jflow.s3.endpoint:10.100.13.77}")
    public void setJflowAmazonEndpointUrl(String jflowAmazonEndpointUrl) {
        JFLOW_AMAZON_ENDPOINT_URL = jflowAmazonEndpointUrl;
    }

    /**
     * 初始化连接，每次使用需要重新连接
     */
    private static AmazonS3 initAmazonS3() {
        AWSCredentials credentials = new BasicAWSCredentials(JFLOW_AMAZON_AWS_ACCESS_KEY, JFLOW_AMAZON_AWS_SECRET_KEY);
        ClientConfiguration clientConfig = new ClientConfiguration();
        clientConfig.setProtocol(Protocol.HTTP);
        AmazonS3 s3Client = new AmazonS3Client(credentials, clientConfig);
        s3Client.setEndpoint(JFLOW_AMAZON_ENDPOINT_URL);
        return s3Client;
    }


    /**
     * 上传文件
     *
     * @param tempFile       待上传文件
     * @param remoteFileName 文件名
     * @return
     */
    public static boolean uploadToS3(File tempFile, String remoteFileName) {
        try {
            AmazonS3 s3 = initAmazonS3();
            if (!s3.doesBucketExistV2(JFLOW_AMAZON_AWS_BUCKET)) {
                s3.createBucket(JFLOW_AMAZON_AWS_BUCKET);
            }
            s3.putObject(new PutObjectRequest(JFLOW_AMAZON_AWS_BUCKET, remoteFileName, tempFile).withCannedAcl(CannedAccessControlList.BucketOwnerFullControl));
            return true;
        } catch (Exception e) {
            log.error("AmazonS3 上传文件[File模式]发生异常 ", e);
        }
        return false;
    }

    /**
     * 上传文件
     *
     * @param multipartFile  待上传文件
     * @param remoteFileName 文件名
     * @return
     */
    public static boolean uploadToS3(CommonsMultipartFile multipartFile, String remoteFileName) {
        InputStream in = null;
        try {
            AmazonS3 s3 = initAmazonS3();
            in = multipartFile.getInputStream();
            FileItem fileItem = multipartFile.getFileItem();

            if (!s3.doesBucketExistV2(JFLOW_AMAZON_AWS_BUCKET)) {
                s3.createBucket(JFLOW_AMAZON_AWS_BUCKET);
            }

            ObjectMetadata omd = new ObjectMetadata();
            omd.setContentType(fileItem.getContentType());
            omd.setContentLength(fileItem.getSize());
            omd.setHeader("filename", fileItem.getName());
            s3.putObject(new PutObjectRequest(JFLOW_AMAZON_AWS_BUCKET, remoteFileName, in, omd).withCannedAcl(CannedAccessControlList.BucketOwnerFullControl));
            return true;
        } catch (Exception e) {
            log.error("AmazonS3 上传文件[InputStream模式]发生异常 ", e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    log.error("AmazonS3 上传文件[关闭InputStream流]发生异常 ", e);
                }
            }
        }
        return false;
    }

    /**
     * 下载文件
     *
     * @param remoteFileName 文件名
     * @return
     */
    public static InputStream downFromS3(String remoteFileName) {
        try {
            AmazonS3 s3 = initAmazonS3();
            GetObjectRequest request = new GetObjectRequest(JFLOW_AMAZON_AWS_BUCKET, remoteFileName);
            S3Object object = s3.getObject(request);
            InputStream input = object.getObjectContent();
            log.info("AmazonS3 下载文件成功......");
            return input;
        } catch (Exception e) {
            log.error("AmazonS3 下载文件发生异常 ", e);
        }
        return null;
    }

    /**
     * 下载文件
     *
     * @param remoteFileName 文件名
     * @param path           下载路径
     */
    public static boolean downFromS3(String remoteFileName, String path) throws Exception {
        try {
            AmazonS3 s3 = initAmazonS3();
            GetObjectRequest request = new GetObjectRequest(JFLOW_AMAZON_AWS_BUCKET, remoteFileName);
            s3.getObject(request, new File(path));
            return true;
        } catch (Exception e) {
            log.error("AmazonS3 下载文件发生异常 ", e);
            throw new Exception("AmazonS3 下载文件发生异常 ");
        }
    }

    /**
     * 删除文件
     *
     * @param remoteFileName 待删除文件名
     * @throws IOException
     */
    public static void delFromS3(String remoteFileName) {
        try {
            AmazonS3 s3 = initAmazonS3();
            s3.deleteObject(JFLOW_AMAZON_AWS_BUCKET, remoteFileName);
            log.error("AmazonS3 删除文件成功......");
        } catch (Exception e) {
            log.error("AmazonS3 删除文件发生异常 ", e);
        }
    }

    /**
     * 获取短链接 带过期时间
     *
     * @param remoteFileName 文件名称
     * @param expiration     过期时间/秒
     */
    public static String getUrlFromS3(String remoteFileName, int expiration) {
        try {
            AmazonS3 s3 = initAmazonS3();
            GeneratePresignedUrlRequest httpRequest = new GeneratePresignedUrlRequest(JFLOW_AMAZON_AWS_BUCKET, remoteFileName);
            httpRequest.setExpiration(new Date(System.currentTimeMillis() + expiration * 1000));
            URL url = s3.generatePresignedUrl(httpRequest);
            return String.valueOf(url);
        } catch (Exception e) {
            log.error("AmazonS3获取临时链接异常 ", e);
        }
        return null;
    }

    /**
     * 获取永久链接
     *
     * @param remoteFileName 文件名称
     */
    public static String getUrlFromS3(String remoteFileName) {
        String url = "";
        try {
            AmazonS3 s3 = initAmazonS3();
            GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(JFLOW_AMAZON_AWS_BUCKET, remoteFileName);
            url = String.valueOf(s3.generatePresignedUrl(urlRequest)).split("\\?")[0];
            if (url.indexOf(remoteFileName) == -1) {
                throw new RuntimeException("url文件名称校验不合法");
            }
            return url;
        } catch (Exception e) {
            log.error("AmazonS3 获取永久链接发生异常 ", e);
            return "";
        }
    }

    /**
     * 根据桶名称获取文件集合
     */
    public static List<S3ObjectSummary> getFileLists() {
        AmazonS3 s3 = initAmazonS3();
        ObjectListing objectListing = s3.listObjects(JFLOW_AMAZON_AWS_BUCKET);
        List<S3ObjectSummary> objectSummaries = objectListing.getObjectSummaries();
        return objectSummaries;
    }

    public static byte[] toByteArray(InputStream input) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[4096];
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
        }
        return output.toByteArray();
    }

    /**
     * 测试用例
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {
        // 1.上传文件
        File file = new File("D:\\signature.pdf");
//        String uuid = UUIDUtil.getUUID();
//        boolean test = uploadToS3(file, "d05c8f0b2fcc4c8fbd0f55b95b6e73fb");
//        System.out.println(test);
//        System.out.println(uuid);

        // 2.获取文件链接
//        String test1 = getUrlFromS3("test");
//        String test2 = getUrlFromS3("test", 30);
//        System.out.println(test1);
//        System.out.println(test2);

        // 3.下载文件
        boolean b = downFromS3("d05c8f0b2fcc4c8fbd0f55b95b6e73fb", "D:\\d05c8f0b2fcc4c8fbd0f55b95b6e73fb-2.pdf");
        System.out.println(b);

//        InputStream input = downFromS3("test");
//        try {
//            File file = new File("D:\\78945.pdf");
//            FileOutputStream fileOutputStream = new FileOutputStream (file);
//            int len = 0;
//            byte[] data = new byte[input.available()];
//            while ((len = input.read(data)) != -1) {
//                fileOutputStream.write(data, 0, len);
//            }
//            fileOutputStream.close();
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

        // 4.删除文件
//        delFromS3("test");
    }
}

